# FastAPI核心模块
from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.responses import FileResponse, HTMLResponse
from fastapi.staticfiles import StaticFiles
# 响应处理模块
from fastapi.responses import Response
# 图像处理库
from PIL import Image
# 内存二进制流操作
from io import BytesIO
import os

import base64
import uvicorn
import torch
import pandas as pd
import matplotlib.pyplot as plt
from  predict2 import predict_with_gui, save_mask_as_image  # 请确保模型代码在model.py中
import os
from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.staticfiles import StaticFiles
import torch
import shutil

# 添加路径配置在FastAPI实例化之前
import sys
import os

# 新增项目根目录到Python路径（重要修复）
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

app = FastAPI()
# 定义静态文件保存目录
save_dir = "static/SaveLoad"
# 本地服务器地址
ip = "127.0.0.1:8000"
# 本地权重文件路径
weight_file = "myapple101.pth"
# 模型类型
model_type = 'mrcnn'
# 设备选择
# device = "cuda" if torch.cuda.is_available() else "cpu"
device = "cpu"
# 挂载静态文件目录
app.mount("/static/SaveLoad", StaticFiles(directory=save_dir), name="SaveLoad")
# 在FastAPI初始化后添加静态文件挂载
app.mount("/static", StaticFiles(directory="static"), name="static")


# uvicorn main:app --host 0.0.0.0 --port 8000
# git pull https://gitee.com/tzjm/fastapitest.git
# 替换根路由为上传界面
@app.get("/", response_class=HTMLResponse)
async def upload_interface():
    return """
<html>
    <head>
        <title>智能苹果检测系统</title>
        <style>
            /* 整体美化 */
            body {
                background: #f8fafc;
                font-family: 'Helvetica Neue', sans-serif;
                padding: 2rem;
                color: #1e293b;
                display: flex;
                flex-direction: column;
                align-items: center; /* 使内容居中 */
            }
            
            /* 标题居中 */
            h1 {
                text-align: center;
                margin-bottom: 2rem;
            }
            
            /* 上传区域美化 */
            .upload-box {
                border: 2px dashed #cbd5e1;
                border-radius: 1.5rem;
                padding: 3rem;
                background: rgba(255, 255, 255, 0.95);
                backdrop-filter: blur(12px);
                margin: 2rem auto; /* 上下外边距为2rem，左右外边距自动 */
                max-width: 400px; /* 限制宽度 */
                transition: all 0.3s ease;
            }
            
            /* 调整图片显示区域 */
            .image-grid > div {
                aspect-ratio: 2/3; /* 宽度为高度的一半 */
                width: 480px;  
                height: 770px;  
                background: white;
                border-radius: 1.5rem;
                box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.05);
                overflow: hidden;
                transition: transform 0.3s ease;
            }

            /* 调整网格布局 */
            .image-grid {
                display: grid;
                grid-template-columns: repeat(2, 480px); /* 根据新宽度调整 */
                gap: 1.5rem; /* 适当减小间距 */
                margin-top: 3rem;
                justify-content: center;
            }
       
           
            /* 卡片设计升级 */
            .image-grid > div {
                background: white;
                border-radius: 1.5rem;
                box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.05);
                overflow: hidden;
                transition: transform 0.3s ease;
                aspect-ratio: 1/2; /* 宽度为高度的一半 */
            }
            
            .image-grid > div:hover {
                transform: translateY(-5px);
                box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
            }
            
            /* 图片显示优化 */
            .image-grid img {
                width: 100%;
                height: 100%;
                object-fit: cover;
                border-bottom: 1px solid #f1f5f9;
                background: linear-gradient(145deg, #f8fafc, #f1f5f9);
            }
            
            /* 标题样式 */
            .image-grid h3 {
                margin: 1.5rem;
                font-size: 1.1rem;
                color: #475569;
                text-align: center;
                padding: 0.8rem;
                background: #f8fafc;
                border-radius: 0.75rem;
            }
            
            /* 按钮美化 */
            button {
                background: linear-gradient(135deg, #3b82f6, #6366f1);
                color: white;
                padding: 0.8rem 2rem;
                border: none;
                border-radius: 0.75rem;
                cursor: pointer;
                transition: all 0.2s ease;
            }
        </style>
    </head>
        <body>
         <h1>苹果检测系统</h1>

         <div class="upload-box">
             <input type="file" id="imageInput" accept="image/*">
             <button onclick="uploadImage()">上传并检测</button>
             <div id="loading" style="display: none;">检测中...</div>
         </div>

         <div id="result">
             <h2>检测结果</h2>
             <div class="image-grid">
                 <div>
                     <h3>原始图片</h3>
                     <img id="originalImg">
                 </div>
                 <div>
                     <h3>掩码叠加</h3>
                     <img id="maskOverlay">
                 </div>
                 <div>
                     <h3>二值掩码</h3>
                     <img id="binaryMask">
                 </div>
                    <div>
                     <h3>box</h3>
                     <img id="boxImage">
                 </div>
             </div>
             <!-- 新增mask信息展示区域 -->
             <div id="maskInfo" style="margin-top: 2rem; padding: 1.5rem; background: #f8fafc; border-radius: 0.75rem;"></div>
         </div>

         <script>
         async function uploadImage() {
             const input = document.getElementById('imageInput');
             const loading = document.getElementById('loading');
             const resultDiv = document.getElementById('result');

             if (!input.files[0]) {
                 alert('请先选择图片');
                 return;
             }

             loading.style.display = 'block';

             try {
                 // 上传文件
                 const formData = new FormData();
                 formData.append('file', input.files[0]);

                 const response = await fetch('/predict/', {
                     method: 'POST',
                     body: formData
                 });

                 if (!response.ok) throw new Error('检测失败');

                 // 获取结果路径
                 const result = await response.json();

                 // 更新图片显示
                 document.getElementById('originalImg').src = result.original_url + '?t=' + Date.now();
                 document.getElementById('maskOverlay').src = result.mask_overlay_url + '?t=' + Date.now();
                 document.getElementById('binaryMask').src = result.binary_mask_url + '?t=' + Date.now();
                 document.getElementById('boxImage').src = result.boxed_image_url + '?t=' + Date.now();

                 // 显示mask信息
                 document.getElementById('maskInfo').innerHTML = result.mask_info_html;

                 resultDiv.style.display = 'block';
             } catch (error) {
                 alert(error.message);
             } finally {
                 loading.style.display = 'none';
             }
         }
         </script>
     </body>
    </html>
    """
@app.get("/static/SaveLoad/{filename}")
async def getImg(filename: str):
    file_path = os.path.join(save_dir, filename)
    print(233333444)
    if not os.path.exists(file_path):
        raise HTTPException(status_code=404, detail="文件未找到")

    return FileResponse(file_path)

@app.get("/hello/{name}")
async def say_hello(name: str):
    """个性化问候端点
    参数：
    - name: 用户姓名
    """
    # 返回个性化问候信息
    return {"message": f"Hello {name}"}


# @app.post("/flip-image")
# async def flip_image(
#     file: UploadFile = File(..., description="上传的图片文件"),
#     direction: str = "horizontal"
# ):
#     try:
#         # 处理图片（原有逻辑）
#         image = Image.open(BytesIO(await file.read()))
#         flip_method = Image.FLIP_LEFT_RIGHT if direction == "horizontal" else Image.FLIP_TOP_BOTTOM
#         flipped = image.transpose(flip_method)
#
#         # 保存原始和处理后的图片
#         os.makedirs(save_dir, exist_ok=True)
#
#         # 原始图片
#         original_path = f"{save_dir}/original_{file.filename}"
#         image.save(original_path)
# # model  func
#             # 处理后的图片
#         processed_path = f"{save_dir}/processed_{file.filename}"
#         flipped.save(processed_path)
#
#
#         return f"""
#         <html>
#         <body style="padding:20px;">
#             <h2>图片处理结果</h2>
#             <div style="display:grid; grid-template-columns:1fr 1fr; gap:20px;">
#                 <div>
#                     <h3>原始图片</h3>
#                     <img src="{ip}/{original_path}" style="max-width:500px;">
#                 </div>
#                 <div>
#                     <h3>翻转后的图片</h3>
#                     <img src="{ip}/{processed_path};" style="max-width:500px;">
#                 </div>
#             </div>
#             <p><a href="/">返回上传</a></p>
#         </body>
#         </html>
#         """
#     except Exception as e:
#         raise HTTPException(500, detail=f"处理失败: {str(e)}")


# @app.post("/upload/")
# async def upload_file(file: UploadFile = File(...)):
#     """
#     上传图片并保存到本地文件夹
#     """
#     try:
#         # 构造保存路径
#         save_path = os.path.join(save_dir, file.filename)
#
#         # 保存文件到本地
#         with open(save_path, "wb") as f:
#             f.write(await file.read())
#
#         # 返回成功信息和访问链接
#         return {
#             "message": "文件上传成功",
#             "file_name": file.filename,
#             "file_path": f"/static/SaveLoad/{file.filename}"
#         }
#     except Exception as e:
#         raise HTTPException(status_code=500, detail=f"保存文件失败：{str(e)}")


# 在文件顶部添加导入
from predictMaturity import predict_maturity

@app.post("/predict/")
async def predict(file: UploadFile = File(...)):
    try:
        #  创建上传图片子目录
        upload_dir = os.path.join(save_dir, "uploadImages")
        os.makedirs(upload_dir, exist_ok=True)
        
        #   正确的文件保存路径
        save_path = os.path.join(upload_dir, file.filename)
        filename = file.filename
        with open(save_path, "wb") as f:
            shutil.copyfileobj(file.file, f)

        results = predict_with_gui(
            data_path=upload_dir,  # 使用上传目录作为数据路径
            weight_file=weight_file,
            model_type=model_type,
            device=device,
            single_image=file.filename
        )
        print("执行 了")
            # 处理mask信息
        mask_info = results[0]['mask_info']
        mask_html = """
        <div class="container mt-4">
            <h3 class="text-center mb-4">Mask 详细信息</h3>
            <div class="row">
        """

        for i, info in enumerate(mask_info):
            mask_html += f"""
            <div class="col-md-6 mb-4">
                <div class="card shadow-sm">
                    <div class="card-body">
                        <h5 class="card-title">Mask {i + 1}</h5>
                        <ul class="list-group list-group-flush">
                            <li class="list-group-item">
                                <strong>中心点坐标(x(px),y(px),depth(米)):</strong> ({info['center_x']}, {info['center_y']}, {info["center_depth"]:.2f})
                            </li>
                            <li class="list-group-item">
                                <strong>像素数量:</strong> {info['pixel_count']}
                            </li>
                            <li class="list-group-item">
                                <strong>成熟度:</strong> 
                                <div class="progress">
                                    <div class="progress-bar" role="progressbar" 
                                         style="width: {info['maturity']}%" 
                                         aria-valuenow="{info['maturity']}" 
                                         aria-valuemin="0" 
                                         aria-valuemax="100">
                                        {info['maturity']:.2f}%
                                    </div>
                                </div>
                            </li>
                            <li class="list-group-item text-center">
                                <img src="/static/SaveLoad/instance/{filename}/mask_{i + 1}_region.png" 
                                     class="img-fluid rounded" 
                                     style="max-width: 300px;">
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
            """

        mask_html += """
            </div>
        </div>
        """

        # 返回结果
        return {
            "original_url": f"/static/SaveLoad/uploadImages/{filename}",
            "mask_overlay_url": f"/static/SaveLoad/compared/{filename}",
            "binary_mask_url": f"/static/SaveLoad/binary/{filename}",
            "boxed_image_url": f"/static/SaveLoad/withBox/{filename}",
            "mask_info_html": mask_html
        }
    except Exception as e:
        raise HTTPException(500, detail=str(e))
 